如何确认视频文件流媒体信息
前言
在对视频文件做流媒体提取时通常需要指定目标流媒体,比如从一个视频文件中提取 acc 音频:
ffmpeg -i input.mp4 -map 0:a:0 out.acc
上面这个命令确实能够从视频文件中提取音频,但如果一个视频文件中同时存在多个音频流怎么办?比如一个电影,有英文音频同时还有中文音频。现在你该怎么办?然后你又会说了,我可以使用下面这个命令呀:
ffmpeg -i input.mp4 -map 0:a out.acc
但是很遗憾,使用这样的命令会将英文音频和中文音频同时导出,没法指定导出具体语言的音频。如果你使用第一个命令虽然导出的确实是一个语音的音频,但是你没有确定导出的是中文的还是英文的,除非试听。
因此,对于这种情况,确定视频文件的流媒体信息就显得很重要了。
确认流媒体信息
实际上,确认视频文件的流媒体信息也很简单,只需要使用 ffprobe 命令即可:
ffprobe input_media.mp4
之后我们就可以通过输出信息来确认流信息了,下面看几个示例:
示例一:标准视频文件
下面是一个标准的视频文件输出示例:
$ ffprobe input.mp4
...
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'input.mp4':
Metadata:
major_brand : isom
minor_version : 512
compatible_brands: isomiso2avc1mp41
encoder : Lavf58.76.100
Duration: 00:05:24.82, start: 0.000000, bitrate: 1468 kb/s
Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p(tv, bt709), 1920x1080 [SAR 1:1 DAR 16:9], 1331 kb/s, 30 fps, 30 tbr, 15360 tbn, 60 tbc (default)
Metadata:
handler_name : VideoHandler
vendor_id : [0][0][0][0]
Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 128 kb/s (default)
Metadata:
handler_name : SoundHandler
vendor_id : [0][0][0][0]
ffprobe 输出的信息会很多,但是真正有用的信息是从 Input 行之后的信息。注意看上面这个输出示例,Metadata 只是一些元数据信息,实际上对确认信息没啥用。接着往下看:
Duration: 00:05:24.82, start: 0.000000, bitrate: 1468 kb/s
这行信息显示,视频文件总时长是5分钟24秒,开始播放时间是从第 0 秒开始。所以,如果你想确认一个视频到底有多长就可以从这里确认。
Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p(tv, bt709), 1920x1080 [SAR 1:1 DAR 16:9], 1331 kb/s, 30 fps, 30 tbr, 15360 tbn, 60 tbc (default)
Metadata:
handler_name : VideoHandler
vendor_id : [0][0][0][0]
这个信息显示,这是视频文件的一个流数据。这个流是一个视频流(Video),并且该流采用的是 H.264 编解码格式。视频分辨率是 1920x1080(2K?),之后还有视频的帧率 30 帧每秒。这个帧率在实际中其实很重要,比如你想对视频实现倍速播放就可以通过导出该视频原始比特流,之后修改帧率来实现倍速效果。
Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 128 kb/s (default)
Metadata:
handler_name : SoundHandler
vendor_id : [0][0][0][0]
这是该视频的第二个流媒体信息,也是最后一个。这个流信息显示该流是一个音频流(Audio),采用的编解码格式是 acc。
现在,你对视频流信息是不是就有了一个最基本的认识?实际上,音频流并不是必须的,比如哑剧就不存在音频流。
我们可以再来看一个没有音频的视频文件输出信息:
示例二:无音频视频文件
$ ffprobe input.mp4
...
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'input.mp4':
Metadata:
major_brand : isom
minor_version : 512
compatible_brands: isomiso2avc1mp41
encoder : Lavf58.76.100
Duration: 00:20:48.07, start: 0.000000, bitrate: 793 kb/s
Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p(tv, bt709), 1920x1080 [SAR 1:1 DAR 16:9], 790 kb/s, 30 fps, 30 tbr, 15360 tbn, 60 tbc (default)
Metadata:
handler_name : VideoHandler
vendor_id : [0][0][0][0]
这次的输出信息相比较上面一个就简单很多。很显然,只有一个使用 H.264 作为编解码的视频流。
示例三:复杂的视频文件
有了上面两个基本的认识之后,我们再来看一个复杂的视频文件。该视频文件采用的容器格式是 mkv,日语音频,同时存在多个语言的字幕(简体中文和繁体中文)。
实际上,对于字幕来说。只要不是硬字幕,其实都是视频文件的一个流。因此,对于这个 mkv 视频文件来说,最多只会有4个流数据。
来看下:
$ ffprobe input.mkv
...
Input #0, matroska,webm, from 'input.mkv':
Metadata:
encoder : libebml v1.4.2 + libmatroska v1.6.4
creation_time : 2023-01-19T11:39:52.000000Z
Duration: 00:23:24.04, start: 0.000000, bitrate: 2269 kb/s
Stream #0:0: Video: hevc (Main 10), yuv420p10le(tv, bt709/unknown/unknown), 1920x1080, SAR 1:1 DAR 16:9, 23.98 fps, 23.98 tbr, 1k tbn, 23.98 tbc (default)
Metadata:
BPS : 2139049
DURATION : 00:23:23.986000000
NUMBER_OF_FRAMES: 33662
NUMBER_OF_BYTES : 375399465
_STATISTICS_WRITING_APP: mkvmerge v67.0.0 ('Under Stars') 64-bit
_STATISTICS_WRITING_DATE_UTC: 2023-01-19 11:39:52
_STATISTICS_TAGS: BPS DURATION NUMBER_OF_FRAMES NUMBER_OF_BYTES
Stream #0:1(jpn): Audio: aac (LC), 44100 Hz, stereo, fltp (default)
Metadata:
title : Main Track
BPS : 128000
DURATION : 00:23:24.041000000
NUMBER_OF_FRAMES: 60467
NUMBER_OF_BYTES : 22464656
_STATISTICS_WRITING_APP: mkvmerge v67.0.0 ('Under Stars') 64-bit
_STATISTICS_WRITING_DATE_UTC: 2023-01-19 11:39:52
_STATISTICS_TAGS: BPS DURATION NUMBER_OF_FRAMES NUMBER_OF_BYTES
Stream #0:2(chi): Subtitle: subrip (default)
Metadata:
title : 简体中文
BPS : 67
DURATION : 00:23:22.200000000
NUMBER_OF_FRAMES: 405
NUMBER_OF_BYTES : 11865
_STATISTICS_WRITING_APP: mkvmerge v67.0.0 ('Under Stars') 64-bit
_STATISTICS_WRITING_DATE_UTC: 2023-01-19 11:39:52
_STATISTICS_TAGS: BPS DURATION NUMBER_OF_FRAMES NUMBER_OF_BYTES
Stream #0:3(chi): Subtitle: subrip
Metadata:
title : 繁體中文
BPS : 67
DURATION : 00:23:22.200000000
NUMBER_OF_FRAMES: 405
NUMBER_OF_BYTES : 11883
_STATISTICS_WRITING_APP: mkvmerge v67.0.0 ('Under Stars') 64-bit
_STATISTICS_WRITING_DATE_UTC: 2023-01-19 11:39:52
_STATISTICS_TAGS: BPS DURATION NUMBER_OF_FRAMES NUMBER_OF_BYTES
从输出的信息可以看出,这个容器格式为 mkv 的视频文件确实有四个流数据。先来,来具体看下这些流:
Stream #0:0: Video: hevc (Main 10), yuv420p10le(tv, bt709/unknown/unknown), 1920x1080, SAR 1:1 DAR 16:9, 23.98 fps, 23.98 tbr, 1k tbn, 23.98 tbc (default)
Metadata:
BPS : 2139049
DURATION : 00:23:23.986000000
NUMBER_OF_FRAMES: 33662
NUMBER_OF_BYTES : 375399465
_STATISTICS_WRITING_APP: mkvmerge v67.0.0 ('Under Stars') 64-bit
_STATISTICS_WRITING_DATE_UTC: 2023-01-19 11:39:52
_STATISTICS_TAGS: BPS DURATION NUMBER_OF_FRAMES NUMBER_OF_BYTES
第一个流显示是一个视频流,这个视频流的编解码格式是 hevc,就是我们通常说的 H.265。视频流的帧率是 23.98,总时长是 23分钟23秒。
Stream #0:1(jpn): Audio: aac (LC), 44100 Hz, stereo, fltp (default)
Metadata:
title : Main Track
BPS : 128000
DURATION : 00:23:24.041000000
NUMBER_OF_FRAMES: 60467
NUMBER_OF_BYTES : 22464656
_STATISTICS_WRITING_APP: mkvmerge v67.0.0 ('Under Stars') 64-bit
_STATISTICS_WRITING_DATE_UTC: 2023-01-19 11:39:52
_STATISTICS_TAGS: BPS DURATION NUMBER_OF_FRAMES NUMBER_OF_BYTES
第二个流是音频流,语言是日语(jpn)。音频的编解码格式是 acc,这个音频的总时长比视频流多了1秒。
Stream #0:2(chi): Subtitle: subrip (default)
Metadata:
title : 简体中文
BPS : 67
DURATION : 00:23:22.200000000
NUMBER_OF_FRAMES: 405
NUMBER_OF_BYTES : 11865
_STATISTICS_WRITING_APP: mkvmerge v67.0.0 ('Under Stars') 64-bit
_STATISTICS_WRITING_DATE_UTC: 2023-01-19 11:39:52
_STATISTICS_TAGS: BPS DURATION NUMBER_OF_FRAMES NUMBER_OF_BYTES
第三个流是字幕流,语言是中文简体。
Stream #0:3(chi): Subtitle: subrip
Metadata:
title : 繁體中文
BPS : 67
DURATION : 00:23:22.200000000
NUMBER_OF_FRAMES: 405
NUMBER_OF_BYTES : 11883
_STATISTICS_WRITING_APP: mkvmerge v67.0.0 ('Under Stars') 64-bit
_STATISTICS_WRITING_DATE_UTC: 2023-01-19 11:39:52
_STATISTICS_TAGS: BPS DURATION NUMBER_OF_FRAMES NUMBER_OF_BYTES
第四个流也是字幕流,语言是中文繁体。
所以,你看。一个视频不管有多少流,输出信息看起来都很简单。只是数量的问题...
导出指定流媒体
现在,我们知道如何确认一个视频的流媒体之后就可以做任何操作了。想要导出流媒体还不是简简单单?
以示例三:复杂的视频文件 为例,该视频文件有两个字幕流。我想要导出繁体字幕该怎么做?
只需要确定好繁体字幕在字幕流中的顺序即可:
Stream #0:2(chi): Subtitle: subrip (default)
Metadata:
title : 简体中文
BPS : 67
DURATION : 00:23:22.200000000
NUMBER_OF_FRAMES: 405
NUMBER_OF_BYTES : 11865
_STATISTICS_WRITING_APP: mkvmerge v67.0.0 ('Under Stars') 64-bit
_STATISTICS_WRITING_DATE_UTC: 2023-01-19 11:39:52
_STATISTICS_TAGS: BPS DURATION NUMBER_OF_FRAMES NUMBER_OF_BYTES
Stream #0:3(chi): Subtitle: subrip
Metadata:
title : 繁體中文
BPS : 67
DURATION : 00:23:22.200000000
NUMBER_OF_FRAMES: 405
NUMBER_OF_BYTES : 11883
_STATISTICS_WRITING_APP: mkvmerge v67.0.0 ('Under Stars') 64-bit
_STATISTICS_WRITING_DATE_UTC: 2023-01-19 11:39:52
_STATISTICS_TAGS: BPS DURATION NUMBER_OF_FRAMES NUMBER_OF_BYTES
很显然,是第二个(即需要为 1),现在导出该繁体字幕就可以使用下面的命令了:
ffmpeg -i input.mkv -map 0:s:1 subtitle.srt
导出之后你打开 subtitle.srt 文件,就会看到确实是中文繁体字幕了:
...
404
00:23:17,160 --> 00:23:20,890
什麼呀 說謊的人要吞一千顆珍珠哦
405
00:23:20,890 --> 00:23:23,730
是一千根針吧 千代